home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / jade / src / glyphs.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  17KB  |  607 lines

  1. /* glyphs.c -- Construction of character images
  2.    Copyright (C) 1994 John Harper <jsh@ukc.ac.uk>
  3.  
  4.    This file is part of Jade.
  5.  
  6.    Jade is free software; you can redistribute it and/or modify it
  7.    under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    Jade is distributed in the hope that it will be useful, but
  12.    WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with Jade; see the file COPYING.    If not, write to
  18.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "jade.h"
  21. #include "jade_protos.h"
  22.  
  23. #include <string.h>
  24. #include <stdlib.h>
  25.  
  26. #ifdef NEED_MEMORY_H
  27. # include <memory.h>
  28. #endif
  29.  
  30. _PR long make_glyph_array(TX *, const u_char *, long, long, u_char *, long, long);
  31. _PR long string_glyph_length(TX *, const u_char *, long);
  32. _PR long glyph_col(TX *, long, long);
  33. _PR long char_col(TX *, long, long);
  34. _PR void calc_cursor_offset(VW *);
  35. _PR void adjust_cursor_to_glyph(VW *);
  36. _PR u_char *char_glyphs(TX *, u_char);
  37. _PR long expand_tabs(TX *, u_char *, long, long, long, long *);
  38.  
  39. _PR void glyphtable_sweep(void);
  40. _PR void glyphtable_prin(VALUE, VALUE);
  41. _PR void glyphs_init(void);
  42. _PR void glyphs_kill(void);
  43.  
  44. /* This table stores the number of glyphs which have to be printed to
  45.    make up each character. 0 is a special case -- TABSIZE spaces.  */
  46. typedef char glyph_widths_t[256];
  47.  
  48. /* This stores the glyphs which have to be printed to create each
  49.    single character, each character (except tabs) can be made of
  50.    no more than 4 glyphs. The above table is used to decide how
  51.    many to use out of the possible 4.  */
  52. typedef u_char glyph_glyphs_t[256][4];
  53.  
  54. typedef struct _GlyphTable{
  55.     u_char        gt_Type;
  56.     u_char        gt_Flags;
  57.     struct _GlyphTable *gt_Next;
  58.     glyph_widths_t    gt_Widths;
  59.     glyph_glyphs_t    gt_Glyphs;
  60. } GlyphTable;
  61. #define GTF_STATIC 1        /* Don't free() this table */
  62.  
  63. static GlyphTable default_glyph_table = {
  64.     V_GlyphTable,
  65.     GTF_STATIC,
  66.     NULL,
  67.     {
  68.     2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2,
  69.     2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  70.     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  71.     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  72.     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  73.     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  74.     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  75.     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
  76.     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  77.     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  78.     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  79.     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  80.     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  81.     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  82.     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  83.     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
  84.     },
  85.     {
  86.     "^@  ", "^A  ", "^B  ", "^C  ", "^D  ", "^E  ", "^F  ", "^G  ",
  87.     "^H  ", " TAB", "^J  ", "^K  ", "^L  ", "^M  ", "^N  ", "^O  ",
  88.     "^P  ", "^Q  ", "^R  ", "^S  ", "^T  ", "^U  ", "^V  ", "^W  ",
  89.     "^X  ", "^Y  ", "^Z  ", "^[  ", "^\\  ", "^]  ", "^^  ", "^_  ",
  90.     "    ", "!   ", "\"   ", "#   ", "$   ", "%   ", "&   ", "'   ",
  91.     "(   ", ")   ", "*   ", "+   ", ",   ", "-   ", ".   ", "/   ",
  92.     "0   ", "1   ", "2   ", "3   ", "4   ", "5   ", "6   ", "7   ",
  93.     "8   ", "9   ", ":   ", ";   ", "<   ", "=   ", ">   ", "?   ",
  94.     "@   ", "A   ", "B   ", "C   ", "D   ", "E   ", "F   ", "G   ",
  95.     "H   ", "I   ", "J   ", "K   ", "L   ", "M   ", "N   ", "O   ",
  96.     "P   ", "Q   ", "R   ", "S   ", "T   ", "U   ", "V   ", "W   ",
  97.     "X   ", "Y   ", "Z   ", "[   ", "\\   ", "]   ", "^   ", "_   ",
  98.     "`   ", "a   ", "b   ", "c   ", "d   ", "e   ", "f   ", "g   ",
  99.     "h   ", "i   ", "j   ", "k   ", "l   ", "m   ", "n   ", "o   ",
  100.     "p   ", "q   ", "r   ", "s   ", "t   ", "u   ", "v   ", "w   ",
  101.     "x   ", "y   ", "z   ", "{   ", "|   ", "}   ", "~   ", "^?  ",
  102.     "\\200", "\\201", "\\202", "\\203", "\\204", "\\205", "\\206", "\\207",
  103.     "\\210", "\\211", "\\212", "\\213", "\\214", "\\215", "\\216", "\\217",
  104.     "\\220", "\\221", "\\222", "\\223", "\\224", "\\225", "\\226", "\\227",
  105.     "\\230", "\\231", "\\232", "\\233", "\\234", "\\235", "\\236", "\\237",
  106.     "\\240", "\\241", "\\242", "\\243", "\\244", "\\245", "\\246", "\\247",
  107.     "\\250", "\\251", "\\252", "\\253", "\\254", "\\255", "\\256", "\\257",
  108.     "\\260", "\\261", "\\262", "\\263", "\\264", "\\265", "\\266", "\\267",
  109.     "\\270", "\\271", "\\272", "\\273", "\\274", "\\275", "\\276", "\\277",
  110.     "\\300", "\\301", "\\302", "\\303", "\\304", "\\305", "\\306", "\\307",
  111.     "\\310", "\\311", "\\312", "\\313", "\\314", "\\315", "\\316", "\\317",
  112.     "\\320", "\\321", "\\322", "\\323", "\\324", "\\325", "\\326", "\\327",
  113.     "\\330", "\\331", "\\332", "\\333", "\\334", "\\335", "\\336", "\\337",
  114.     "\\340", "\\341", "\\342", "\\343", "\\344", "\\345", "\\346", "\\347",
  115.     "\\350", "\\351", "\\252", "\\353", "\\354", "\\355", "\\356", "\\357",
  116.     "\\360", "\\361", "\\362", "\\363", "\\364", "\\365", "\\366", "\\367",
  117.     "\\370", "\\371", "\\372", "\\373", "\\374", "\\375", "\\376", "\\377"
  118.     }
  119. };
  120.  
  121. static GlyphTable *gt_chain = &default_glyph_table;
  122.  
  123. /* From the array of characters SRC, build an array of glyph codes DST.
  124.    SRC contains at least SRC-LEN characters. On return, there is guaranteed
  125.    to be no more than DST-LEN glyph codes in DST, the actual number is
  126.    the return value of the function. No glyphs are copied to DST until
  127.    DST-START glyphs have gone before. SRC-ORIG is the *true glyph* position
  128.    of SRC, for calculating tab sizes.  */
  129. long
  130. make_glyph_array(TX *tx, const u_char *src, long srcOrig, long srcLen,
  131.          register u_char *dst, long dstStart, long dstLen)
  132. {
  133.     glyph_widths_t *width_table = &VGLYPHTAB(tx->tx_GlyphTable)->gt_Widths;
  134.     glyph_glyphs_t *glyph_table = &VGLYPHTAB(tx->tx_GlyphTable)->gt_Glyphs;
  135.     register long i = 0;
  136.     if(dstStart != 0)
  137.     {
  138.     /* Skip DSTSTART glyphs */
  139.     register long j = 0;
  140.     while((j < dstStart) && (srcLen-- > 0))
  141.     {
  142.         register int w = (*width_table)[*src++];
  143.         if(w == 0)
  144.         {
  145.         j += tx->tx_TabSize - ((j + srcOrig) % tx->tx_TabSize);
  146.         if(j > dstStart)
  147.         {
  148.             i = j - dstStart;
  149.             memset(dst, ' ', i);
  150.             dst += i;
  151.             break;
  152.         }
  153.         }
  154.         else
  155.         {
  156.         j += w;
  157.         if(j > dstStart)
  158.         {
  159.             i = j - dstStart;
  160.             memcpy(dst, &(*glyph_table)[src[-1]][w-i], i);
  161.             dst += i;
  162.             break;
  163.         }
  164.         }
  165.     }
  166.     }
  167.     while((i < dstLen) && (srcLen-- > 0))
  168.     {
  169.     register u_char c;
  170.     switch((*width_table)[c = *src++])
  171.     {
  172.     case 0:
  173.         {
  174.         /* TAB special case */
  175.         register int size = tx->tx_TabSize - ((i + srcOrig + dstStart)
  176.                               % tx->tx_TabSize);
  177.         memset(dst, ' ', size);
  178.         dst += size;
  179.         i += size;
  180.         }
  181.         break;
  182.     case 1:
  183.         *dst++ = (*glyph_table)[c][0];
  184.         i++;
  185.         break;
  186.     case 2:
  187.         *dst++ = (*glyph_table)[c][0];
  188.         *dst++ = (*glyph_table)[c][1];
  189.         i += 2;
  190.         break;
  191.     case 3:
  192.         *dst++ = (*glyph_table)[c][0];
  193.         *dst++ = (*glyph_table)[c][1];
  194.         *dst++ = (*glyph_table)[c][2];
  195.         i += 3;
  196.         break;
  197.     case 4:
  198.         *dst++ = (*glyph_table)[c][0];
  199.         *dst++ = (*glyph_table)[c][1];
  200.         *dst++ = (*glyph_table)[c][2];
  201.         *dst++ = (*glyph_table)[c][3];
  202.         i += 4;
  203.         break;
  204.     }
  205.     }
  206.     return(i);
  207. }
  208.  
  209. /* Returns the number of glyphs needed to draw the string SRC.    */
  210. long
  211. string_glyph_length(TX *tx, const u_char *src, long srcLen)
  212. {
  213.     glyph_widths_t *width_table = &VGLYPHTAB(tx->tx_GlyphTable)->gt_Widths;
  214.     register long w;
  215.     for(w = 0; srcLen-- > 0;)
  216.     {
  217.     register int w1 = (*width_table)[*src++];
  218.     if(w1 == 0)
  219.         w += tx->tx_TabSize - (w % tx->tx_TabSize);
  220.     else
  221.         w += w1;
  222.     }
  223.     return(w);
  224. }
  225.  
  226. /* Return the glyph index of (COL,LINE) in TX.    */
  227. long
  228. glyph_col(TX *tx, long col, long linenum)
  229. {
  230.     LINE *line = tx->tx_Lines + linenum;
  231.     if(col >= line->ln_Strlen)
  232.     {
  233.     return((string_glyph_length(tx, line->ln_Line, line->ln_Strlen - 1)
  234.         + (col - (line->ln_Strlen - 1))));
  235.     }
  236.     else
  237.     return(string_glyph_length(tx, line->ln_Line, col));
  238. }
  239.  
  240. /* Find how many chars to glyph position col. */
  241. long
  242. char_col(TX *tx, long col, long linenum)
  243. {
  244.     LINE *line = tx->tx_Lines + linenum;
  245.     u_char *src = line->ln_Line;
  246.     long srclen = line->ln_Strlen - 1;
  247.     glyph_widths_t *width_table = &VGLYPHTAB(tx->tx_GlyphTable)->gt_Widths;
  248.     register long w = 0;
  249.     while((w < col) && (srclen-- != 0))
  250.     {
  251.     register int w1 = (*width_table)[*src++];
  252.     if(w1 == 0)
  253.         w += tx->tx_TabSize - (w % tx->tx_TabSize);
  254.     else
  255.         w += w1;
  256.     }
  257.     if(srclen == -1)
  258.     return((line->ln_Strlen - 1) + (col - w));
  259.     else
  260.     return(src - line->ln_Line);
  261. }
  262.  
  263. void
  264. calc_cursor_offset(VW *vw)
  265. {
  266.     TX *tx = vw->vw_Tx;
  267.     if(!((tx == vw->vw_LastCursorTx)
  268.      && (tx->tx_Changes == vw->vw_LastCursorChanges)
  269.      && POS_EQUAL_P(&vw->vw_CursorPos, &vw->vw_LastCursorPos)))
  270.     {
  271.     /* Have to recalculate the number of glyphs before the cursor. */
  272.     vw->vw_LastCursorOffset = glyph_col(tx, vw->vw_CursorPos.pos_Col,
  273.                         vw->vw_CursorPos.pos_Line);
  274.     vw->vw_LastCursorTx = tx;
  275.     vw->vw_LastCursorChanges = tx->tx_Changes;
  276.     vw->vw_LastCursorPos = vw->vw_CursorPos;
  277.     }
  278. }
  279.  
  280. /* Sets the vw_CursorPos.pos_Col so that the cursor's glyph pos is the same
  281.    as vw_LastCursorOffset.  */
  282. void
  283. adjust_cursor_to_glyph(VW *vw)
  284. {
  285.     vw->vw_CursorPos.pos_Col = char_col(vw->vw_Tx, vw->vw_LastCursorOffset,
  286.                     vw->vw_CursorPos.pos_Line);
  287. }
  288.  
  289. u_char *
  290. char_glyphs(TX *tx, u_char ch)
  291. {
  292.     return(&VGLYPHTAB(tx->tx_GlyphTable)->gt_Glyphs[ch][0]);
  293. }
  294.  
  295. /* Expands any tabs in the line LINE-NUM in TX, between the glyph
  296.    positions START-GLYPH and END-GLYPH into the buffer DST. The
  297.    actual number of characters copied into DST (won't be any more
  298.    than (END-GLYPH - START-GLYPH) is returned.    If WIDTH-P is non-NULL
  299.    the true width (in glyphs) of the copied portion is stored there. */
  300. long
  301. expand_tabs(TX *tx, u_char *dst, long start_glyph, long end_glyph,
  302.         long linenum, long *width_p)
  303. {
  304.     LINE *line = tx->tx_Lines + linenum;
  305.     u_char *src = line->ln_Line;
  306.     u_char *orig_dst = dst;
  307.     long srclen = line->ln_Strlen - 1;
  308.     glyph_widths_t *width_table = &VGLYPHTAB(tx->tx_GlyphTable)->gt_Widths;
  309.     register long i = 0;
  310.     if(start_glyph > 0)
  311.     {
  312.     while(srclen-- != 0)
  313.     {
  314.         register int w1 = (*width_table)[*src++];
  315.         if(w1 == 0)
  316.         {
  317.         i += tx->tx_TabSize - (i % tx->tx_TabSize);
  318.         if(i > start_glyph)
  319.         {
  320.             memset(dst, ' ', i - start_glyph);
  321.             dst += i - start_glyph;
  322.             break;
  323.         }
  324.         }
  325.         else
  326.         {
  327.         i += w1;
  328.         if(i > start_glyph)
  329.         {
  330.             *dst++ = src[-1];
  331.             break;
  332.         }
  333.         }
  334.     }
  335.     }
  336.     if(srclen == -1)
  337.     return(dst - orig_dst);
  338.     while(srclen-- != 0)
  339.     {
  340.     u_char c = *src++;
  341.     register int w1 = (*width_table)[c];
  342.     if(w1 == 0)
  343.     {
  344.         w1 = tx->tx_TabSize - (i % tx->tx_TabSize);
  345.         if(w1 + i >= end_glyph)
  346.         {
  347.  
  348.         memset(dst, ' ', end_glyph - i);
  349.         dst += end_glyph - i;
  350.         break;
  351.         }
  352.         memset(dst, ' ', w1);
  353.         dst += w1;
  354.         i += w1;
  355.     }
  356.     else
  357.     {
  358.         *dst++ = c;
  359.         i += w1;
  360.         if(i >= end_glyph)
  361.         break;
  362.     }
  363.     }
  364.     if(width_p)
  365.     *width_p = i - start_glyph;
  366.     return(dst - orig_dst);
  367. }
  368.  
  369. _PR VALUE cmd_glyph_table_p(VALUE arg);
  370. DEFUN("glyph-table-p", cmd_glyph_table_p, subr_glyph_table_p, (VALUE arg), V_Subr1, DOC_glyph_table_p) /*
  371. ::doc:glyph_table_p::
  372. glyph-table-p ARG
  373.  
  374. Returns t if ARG is a glyph-table.
  375. ::end:: */
  376. {
  377.     return(GLYPHTABP(arg) ? sym_t : sym_nil);
  378. }
  379.  
  380. _PR VALUE cmd_char_to_glyph_pos(VALUE vpos, VALUE tx);
  381. DEFUN("char-to-glyph-pos", cmd_char_to_glyph_pos, subr_char_to_glyph_pos, (VALUE vpos, VALUE tx), V_Subr2, DOC_char_to_glyph_pos) /*
  382. ::doc:char_to_glyph_pos::
  383. char-to-glyph-pos [POS] [BUFFER]
  384.  
  385. From the character position POS, find its true *physical* position when
  386. rendered.
  387. ::end:: */
  388. {
  389.     POS pos;
  390.     if(!BUFFERP(tx))
  391.     tx = VAL(curr_vw->vw_Tx);
  392.     if(POSP(vpos))
  393.     pos = VPOS(vpos);
  394.     else
  395.     pos = *get_tx_cursor(VTX(tx));
  396.     pos.pos_Col = glyph_col(VTX(tx), pos.pos_Col, pos.pos_Line);
  397.     return(make_lpos(&pos));
  398. }
  399.  
  400. _PR VALUE cmd_glyph_to_char_pos(VALUE vpos, VALUE tx);
  401. DEFUN("glyph-to-char-pos", cmd_glyph_to_char_pos, subr_glyph_to_char_pos, (VALUE vpos, VALUE tx), V_Subr2, DOC_glyph_to_char_pos) /*
  402. ::doc:glyph_to_char_pos::
  403. glyph-to-char-pos POS [BUFFER]
  404.  
  405. For the physical position POS, find the closest matching actual character
  406. position.
  407. ::end:: */
  408. {
  409.     POS pos;
  410.     if(!BUFFERP(tx))
  411.     tx = VAL(curr_vw->vw_Tx);
  412.     DECLARE1(vpos, POSP);
  413.     pos = VPOS(vpos);
  414.     pos.pos_Col = char_col(VTX(tx), pos.pos_Col, pos.pos_Line);
  415.     return(make_lpos(&pos));
  416. }
  417.  
  418. _PR VALUE cmd_default_glyph_table(void);
  419. DEFUN("default-glyph-table", cmd_default_glyph_table, subr_default_glyph_table, (void), V_Subr0, DOC_default_glyph_table) /*
  420. ::doc:default_glyph_table::
  421. default-glyph-table
  422.  
  423. Returns the standard glyph-table.
  424. ::end:: */
  425. {
  426.     return(VAL(&default_glyph_table));
  427. }
  428.  
  429. _PR VALUE cmd_make_glyph_table(VALUE src);
  430. DEFUN("make-glyph-table", cmd_make_glyph_table, subr_make_glyph_table, (VALUE src), V_Subr1, DOC_make_glyph_table) /*
  431. ::doc:make_glyph_table::
  432. make-glyph-table SRC
  433.  
  434. Creates a new glyph-table. If SRC is a glyph-table it will be copied, else if
  435. SRC is a buffer that buffer's glyph-table will be copied. If SRC is nil the
  436. default glyph-table will be copied.
  437. ::end:: */
  438. {
  439.     GlyphTable *newgt = mymalloc(sizeof(GlyphTable));
  440.     if(newgt)
  441.     {
  442.     GlyphTable *srcgt;
  443.     if(GLYPHTABP(src))
  444.         srcgt = VGLYPHTAB(src);
  445.     else if(BUFFERP(src))
  446.         srcgt = VGLYPHTAB(VTX(src)->tx_GlyphTable);
  447.     else
  448.         srcgt = &default_glyph_table;
  449.     memcpy(newgt, srcgt, sizeof(GlyphTable));
  450.     newgt->gt_Flags &= ~GTF_STATIC;
  451.     newgt->gt_Next = gt_chain;
  452.     gt_chain = newgt;
  453.     data_after_gc += sizeof(GlyphTable);
  454.     return(VAL(newgt));
  455.     }
  456.     return(sym_nil);
  457. }
  458.  
  459. _PR VALUE cmd_set_glyph(VALUE gt, VALUE ch, VALUE glyph);
  460. DEFUN("set-glyph", cmd_set_glyph, subr_set_glyph, (VALUE gt, VALUE ch, VALUE glyph), V_Subr3, DOC_set_glyph) /*
  461. ::doc:set_glyph::
  462. set-glyph GLYPH-TABLE CHARACTER GLYPH-STRING
  463.  
  464. Make the renderer draw the string GLYPH-STRING (no more than 4 characters)
  465. for each character CHARACTER in any buffers which use the GLYPH-TABLE.
  466. ::end:: */
  467. {
  468.     int glyphlen;
  469.     TX *tx;
  470.     DECLARE1(gt, GLYPHTABP);
  471.     DECLARE2(ch, NUMBERP);
  472.     DECLARE3(glyph, STRINGP);
  473.     if((VNUM(ch) < 0) || (VNUM(ch) >= 256))
  474.     {
  475.     signal_arg_error(ch, 1);
  476.     return(NULL);
  477.     }
  478.     glyphlen = STRING_LEN(glyph);
  479.     if(glyphlen > 4)
  480.     {
  481.     signal_arg_error(glyph, 2);
  482.     return(NULL);
  483.     }
  484.     VGLYPHTAB(gt)->gt_Widths[VNUM(ch)] = glyphlen;
  485.     if(glyphlen == 0)
  486.     {
  487.     /* put a space in the first character */
  488.     VGLYPHTAB(gt)->gt_Glyphs[VNUM(ch)][0] = ' ';
  489.     }
  490.     else
  491.     memcpy(&VGLYPHTAB(gt)->gt_Glyphs[VNUM(ch)][0], VSTR(glyph), glyphlen);
  492.  
  493.     tx = buffer_chain;
  494.     while(tx)
  495.     {
  496.     /* refresh all buffers which use this glyph table */
  497.     if(tx->tx_GlyphTable == gt)
  498.         tx->tx_Flags |= TXFF_REFRESH_ALL;
  499.     tx = tx->tx_Next;
  500.     }
  501.  
  502.     return(sym_t);
  503. }
  504.  
  505. _PR VALUE cmd_get_glyph(VALUE gt, VALUE ch);
  506. DEFUN("get-glyph", cmd_get_glyph, subr_get_glyph, (VALUE gt, VALUE ch), V_Subr2, DOC_get_glyph) /*
  507. ::doc:get_glyph::
  508. get-glyph GLYPH-TABLE CHARACTER
  509.  
  510. Return the string which is the rendered representation of CHARACTER in
  511. GLYPH-TABLE.
  512. ::end:: */
  513. {
  514.     DECLARE1(gt, GLYPHTABP);
  515.     DECLARE2(ch, NUMBERP);
  516.     if((VNUM(ch) < 0) || (VNUM(ch) >= 256))
  517.     {
  518.     signal_arg_error(ch, 1);
  519.     return(NULL);
  520.     }
  521.     return(string_dupn(&VGLYPHTAB(gt)->gt_Glyphs[VNUM(ch)][0],
  522.                VGLYPHTAB(gt)->gt_Widths[VNUM(ch)]));
  523. }
  524.  
  525. _PR VALUE cmd_buffer_glyph_table(VALUE tx);
  526. DEFUN("buffer-glyph-table", cmd_buffer_glyph_table, subr_buffer_glyph_table, (VALUE tx), V_Subr1, DOC_buffer_glyph_table) /*
  527. ::doc:buffer_glyph_table::
  528. buffer-glyph-table [BUFFER]
  529.  
  530. Returns the glyph-table being used in BUFFER.
  531. ::end:: */
  532. {
  533.     if(!BUFFERP(tx))
  534.     tx = VAL(curr_vw->vw_Tx);
  535.     return(VTX(tx)->tx_GlyphTable);
  536. }
  537.  
  538. _PR VALUE cmd_set_buffer_glyph_table(VALUE tx, VALUE gt);
  539. DEFUN("set-buffer-glyph-table", cmd_set_buffer_glyph_table, subr_set_buffer_glyph_table, (VALUE tx, VALUE gt), V_Subr2, DOC_set_buffer_glyph_table) /*
  540. ::doc:set_buffer_glyph_table::
  541. set-buffer-glyph-table [BUFFER] GLYPH-TABLE
  542.  
  543. Sets the glyph-table being used in BUFFER to GLYPH-TABLE.
  544. ::end:: */
  545. {
  546.     if(!BUFFERP(tx))
  547.     tx = VAL(curr_vw->vw_Tx);
  548.     DECLARE2(gt, GLYPHTABP);
  549.     VTX(tx)->tx_GlyphTable = gt;
  550.     VTX(tx)->tx_Flags |= TXFF_REFRESH_ALL;
  551.     return(gt);
  552. }
  553.  
  554. void
  555. glyphtable_sweep(void)
  556. {
  557.     GlyphTable *gt = gt_chain;
  558.     gt_chain = NULL;
  559.     while(gt)
  560.     {
  561.     GlyphTable *nxt = gt->gt_Next;
  562.     if(!GC_MARKEDP(VAL(gt)) && !(gt->gt_Flags & GTF_STATIC))
  563.         myfree(gt);
  564.     else
  565.     {
  566.         GC_CLR(VAL(gt));
  567.         gt->gt_Next = gt_chain;
  568.         gt_chain = gt;
  569.     }
  570.     gt = nxt;
  571.     }
  572. }
  573.  
  574. void
  575. glyphtable_prin(VALUE strm, VALUE obj)
  576. {
  577.     stream_puts(strm, "#<glyph-table>", -1, FALSE);
  578. }
  579.  
  580. void
  581. glyphs_init(void)
  582. {
  583.     ADD_SUBR(subr_glyph_table_p);
  584.     ADD_SUBR(subr_glyph_to_char_pos);
  585.     ADD_SUBR(subr_char_to_glyph_pos);
  586.     ADD_SUBR(subr_default_glyph_table);
  587.     ADD_SUBR(subr_make_glyph_table);
  588.     ADD_SUBR(subr_set_glyph);
  589.     ADD_SUBR(subr_get_glyph);
  590.     ADD_SUBR(subr_buffer_glyph_table);
  591.     ADD_SUBR(subr_set_buffer_glyph_table);
  592. }
  593.  
  594. void
  595. glyphs_kill(void)
  596. {
  597.     GlyphTable *gt = gt_chain;
  598.     while(gt)
  599.     {
  600.     GlyphTable *nxt = gt->gt_Next;
  601.     if(!(gt->gt_Flags & GTF_STATIC))
  602.         myfree(gt);
  603.     gt = nxt;
  604.     }
  605.     gt_chain = NULL;
  606. }
  607.